package com.dcy.workflow.service;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dcy.common.base.service.DcyBaseService;
import com.dcy.common.constant.SqlConstant;
import com.dcy.common.enums.FlowTypeEnum;
import com.dcy.workflow.convert.FlowNodeConvert;
import com.dcy.workflow.dao.FlowNodeDao;
import com.dcy.workflow.dao.FlowNodeDeptDao;
import com.dcy.workflow.dao.FlowNodeRoleDao;
import com.dcy.workflow.dao.FlowNodeUserDao;
import com.dcy.workflow.model.FlowNode;
import com.dcy.workflow.model.FlowNodeDept;
import com.dcy.workflow.model.FlowNodeRole;
import com.dcy.workflow.model.FlowNodeUser;
import com.dcy.workflow.vo.in.FlowNodeSaveInVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 流程节点表 服务实现类
 * </p>
 *
 * @author dcy
 * @since 2021-06-08
 */
@RequiredArgsConstructor
@Service
public class FlowNodeService extends DcyBaseService {

    private final FlowNodeDao flowNodeDao;
    private final FlowNodeUserDao flowNodeUserDao;
    private final FlowNodeRoleDao flowNodeRoleDao;
    private final FlowNodeDeptDao flowNodeDeptDao;
    private final FlowNodeConvert flowNodeConvert = FlowNodeConvert.INSTANCE;

    /**
     * 保存流程和审批节点关联
     *
     * @param flowNodeSaveInVOS
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean saveFlowNode(List<FlowNodeSaveInVO> flowNodeSaveInVOS) {
        List<FlowNode> flowNodes = flowNodeConvert.toFlowNode(flowNodeSaveInVOS);
        boolean success = flowNodeDao.saveOrUpdateBatch(flowNodes);
        if (success) {
            // 添加关联表
            flowNodes.forEach(flowNode -> {
                FlowTypeEnum flowType = FlowTypeEnum.getByCode(flowNode.getFlowType());
                switch (flowType) {
                    case USER:
                        flowNodeUserDao.remove(Wrappers.<FlowNodeUser>lambdaQuery().eq(FlowNodeUser::getFlowNodeId, flowNode.getId()));
                        List<FlowNodeUser> flowNodeUsers = new ArrayList<>();
                        flowNode.getIds().forEach(s -> flowNodeUsers.add(new FlowNodeUser().setFlowNodeId(flowNode.getId()).setUserId(s)));
                        flowNodeUserDao.saveBatch(flowNodeUsers);
                        break;
                    case ROLE:
                        flowNodeRoleDao.remove(Wrappers.<FlowNodeRole>lambdaQuery().eq(FlowNodeRole::getFlowNodeId, flowNode.getId()));
                        List<FlowNodeRole> flowNodeRoles = new ArrayList<>();
                        flowNode.getIds().forEach(s -> flowNodeRoles.add(new FlowNodeRole().setFlowNodeId(flowNode.getId()).setRoleId(s)));
                        flowNodeRoleDao.saveBatch(flowNodeRoles);
                        break;
                    case DEPT:
                        flowNodeDeptDao.remove(Wrappers.<FlowNodeDept>lambdaQuery().eq(FlowNodeDept::getFlowNodeId, flowNode.getId()));
                        List<FlowNodeDept> flowNodeDepts = new ArrayList<>();
                        flowNode.getIds().forEach(s -> flowNodeDepts.add(new FlowNodeDept().setFlowNodeId(flowNode.getId()).setDeptId(s)));
                        flowNodeDeptDao.saveBatch(flowNodeDepts);
                        break;
                    default:
                }
            });
        }
        return success;
    }

    /**
     * 根据flowNode 获取审批 ids
     *
     * @param flowNode
     * @return
     */
    public List<String> getIds(FlowNode flowNode) {
        List<String> ids = new ArrayList<>();
        FlowTypeEnum flowType = FlowTypeEnum.getByCode(flowNode.getFlowType());
        if (flowType != null) {
            switch (flowType) {
                case USER:
                    ids = flowNodeUserDao.list(Wrappers.<FlowNodeUser>lambdaQuery().select(FlowNodeUser::getUserId).eq(FlowNodeUser::getFlowNodeId, flowNode.getId()))
                            .stream().map(FlowNodeUser::getUserId).collect(Collectors.toList());
                    break;
                case ROLE:
                    ids = flowNodeRoleDao.list(Wrappers.<FlowNodeRole>lambdaQuery().select(FlowNodeRole::getRoleId).eq(FlowNodeRole::getFlowNodeId, flowNode.getId()))
                            .stream().map(FlowNodeRole::getRoleId).collect(Collectors.toList());
                    break;
                case DEPT:
                    ids = flowNodeDeptDao.list(Wrappers.<FlowNodeDept>lambdaQuery().select(FlowNodeDept::getDeptId).eq(FlowNodeDept::getFlowNodeId, flowNode.getId()))
                            .stream().map(FlowNodeDept::getDeptId).collect(Collectors.toList());
                    break;
                default:
            }
        }
        return ids;
    }

    /**
     * 根据流程定义id 和 节点id查询对象
     *
     * @param procDefId
     * @param activityId
     * @return
     */
    public FlowNode getOneByProcDefIdAndFlowId(String procDefId, String activityId) {
        return flowNodeDao.getOne(Wrappers.<FlowNode>lambdaQuery()
                .eq(FlowNode::getProcDefId, procDefId)
                .eq(FlowNode::getFlowId, activityId)
                .last(SqlConstant.DEFAULT_ONE_LAST_SQL));
    }

    public FlowNode getOntByProcDefIdAndFlowIdAndFlowName(String procDefId, String flowId, String flowName) {
        return flowNodeDao.getOne(Wrappers.<FlowNode>lambdaQuery()
                .eq(FlowNode::getProcDefId, procDefId)
                .eq(FlowNode::getFlowId, flowId)
                .eq(FlowNode::getFlowName, flowName)
                .last(SqlConstant.DEFAULT_ONE_LAST_SQL));
    }
}
